package org.jprogger.myworld.api.http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.jprogger.myworld.api.ApiServiceInvocationException;
import org.jprogger.myworld.api.request.ApiRequest;


/**
 * Underlying HTTP client. Use for API Services call
 * 
 * @author jprogger
 *
 */
public class ApiServiceHttpClient {

	private static ApiServiceHttpClient instance = null;
		
	private HttpClient httpClient;
	
	public static ApiServiceHttpClient getInstance() {
		if (instance == null)
		{
			instance = new ApiServiceHttpClient();
		}
		return instance;
	}
	
	private ApiServiceHttpClient() {
				
	       HttpParams params = new BasicHttpParams();
	       HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
	       HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
	       HttpProtocolParams.setUseExpectContinue(params, false);

	       SchemeRegistry schReg = new SchemeRegistry();
	       schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
	       schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
	       ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(params, schReg);
	       httpClient = new DefaultHttpClient(connectionManager, params);
	}
	
	public String sendRequest(ApiRequest request) throws ApiServiceInvocationException {
		
		HttpGet httpGet = null;
		HttpResponse httpResponse = null;
		Map<String, Object> params = request.getApiRequestParams().getParameterMap();
		
		StringBuilder urlBuilder = new StringBuilder();
		urlBuilder.append(request.getApiRequestUrl());
		urlBuilder.append("?");
		int entryCount = params.size() - 1;
		for (Map.Entry<String, Object> param : params.entrySet()) 
		{
			urlBuilder.append(param.getKey());
			urlBuilder.append("=");
			urlBuilder.append(param.getValue());
			if (entryCount > 0) 
			{
				urlBuilder.append("&");
			}
			--entryCount;
		}
		httpGet = new HttpGet(urlBuilder.toString());
		try 
		{
			System.out.println(httpGet.getRequestLine());
			httpResponse = httpClient.execute(httpGet);
			if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
			{
				HttpEntity entity = httpResponse.getEntity();
				if (entity != null) 
		        {
					String line;
					StringBuilder sb = new StringBuilder();
		            BufferedReader reader = 
		            	new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
		            while ((line = reader.readLine()) != null) 
		            {
		                sb.append(line).append("\n");
		            }
		            return sb.toString();
		        }
			}
			else 
			{
				throw new ApiServiceInvocationException("Http exception!");
			}
		} 
		catch (ClientProtocolException e) 
		{
			throw new ApiServiceInvocationException(e);
		}
		catch (IOException e) 
		{
			throw new ApiServiceInvocationException(e);
		}
		return null;
	}
}
